
const LONG_DELAY = 2000;
const NORMAL_DELAY = 500;

var QcloudBucket = {
    Bucket: 'imagestore-1255572104',
    Region: 'ap-beijing',
    Path: 'layout/'
}


module.exports = app => {
    class SecurityController extends app.Controller {
        //index test
        //GET, /api/v1/security/mqtt/serverInfo
        /*
         * get mqtt Server info , { host, port }
         */
        async mqttServerInfo(){
            this.ctx.status = 200
            this.ctx.body = {
                    host: app.config.mqtt.host,
                    web_port: app.config.mqtt.web_port,
                    tcp_port: app.config.mqtt.tcp_port

            }
        }

        /*
         * GET, /api/v1/security/shopAreas
         * content-type: application/json
         *
         * ------------------------------
         *
         * resp:
         * body: {
         *      [{
         *          id: # areaId,
         *          contract:  //phone number
         *          charger: # administrator
         *      },
         *      ]
         * }
         */
        async getAreas() {
            try{
                var result = await this.app.db.query( 'SELECT * FROM areas ' );
                this.ctx.status = 200;
                this.ctx.body = result;
            }
            catch( error ){
                this.ctx.status = 500;
                this.ctx.body = { error } ;
            }
        }
        //GET, /api/v1/protectors
        /*
         * get all protectors
         */
        async allProtectors(){
            var protectors = await this.app.db.any( "SELECT * FROM protectors " );
            this.ctx.status = 200;
            this.ctx.body = { protectors: protectors };
        }

        //GET, /api/v1/shops
        /*
         * get all shops
         *
         */
        async allShops(){
          var shops = await this.app.db.any( 'SELECT * FROM  shops ' )
          this.ctx.status = 200
          this.ctx.body = {
            shops: shops
          }
        }

        //GET, /api/v1/security/shops
        /*
         * get all shops which is assigned with protector
         */
        async shops() {
            try {
                console.log( "get shops request" )
                var query = 'SELECT '+
                'shops.*, protectors.mac '+
                'FROM  shops , protectors '+
                'WHERE protectors.shopid = shops.id';

                var shops = await this.app.db.any( query );


                this.ctx.status = 200;
                this.ctx.body = {
                    shops: shops
                }
            } catch ( error ) {
                this.ctx.logger.error( 'get shops with security error: ', error );
                console.log( error )
                this.ctx.status = 500
                this.ctx.body = { error }
            }
        }
        //GET, /api/v1/security/protectors
        /*
         * get all protectors which is presented at now
         */
        async protectors() {
            try{
                console.log( "get protectors request ")
                var query = 'SELECT  * from protectors WHERE shopid IS NOT NULL '
                var protectors = await this.app.db.any( query )

                this.ctx.status = 200
                this.ctx.body = {
                    protectors: protectors
                }
            } catch ( error ) {
                this.ctx.logger.error( 'get protectors error: ', error );
                console.log( error )
                this.ctx.status = 400
                this.ctx.body = {
                    error: error
                }
            }
        }
        /*
         * POST, /api/v1/security/protectors/add
         * content-type: application/json
         * body: {
         *      mac:  #device's mac
         *      ip:   #device's ip
         *  }
         */
        /*
         * when protector is presented , add the new protector
         */

        async insertProtector( ){
            try{
                console.log( 'insert protectors: ', this.ctx.request.body )
                var mac = this.ctx.request.body.mac.replace( /\:/g, "" )
                var ip = this.ctx.request.body.ip

                var protectors = await this.app.db.query( 'SELECT mac, ip from protectors WHERE mac = $1', [mac])
                if( protectors.length > 0 ){
                    await this.app.db.query( 'UPDATE protectors SET ip = $2 WHERE mac = $1 ', [mac, ip])

                    //publish the "monitorPubChannel" to device,
                    //then device can report status  to monitor
                    try{
                        var message = JSON.stringify( {
                            type: "init",
                            publishKey: app.monitorPubKey,
                            publishChannel: app.monitorChannel + mac
                        })
                        app.mqtt.publish( 'device/'+mac,  message )
                    } catch( error ){
                        console.log( error );
                        this.ctx.status = 400
                        this.ctx.body = {  error: "the device " + mac + " is offline, can not connected ", }
                        return
                    }
                    this.ctx.status = 200
                    this.ctx.body = {
                        subscribeKey : app.deviceSubKey,
                        subscribeChannel: app.deviceChannel + "/" + mac,
                        publishKey: app.monitorPubKey,
                        publishChannel: app.monitorChannel + "/" + mac,
                        host: app.config.mqtt.host,
                        port: app.config.mqtt.port
                    }
                } else {
                    await this.app.db.query( 'INSERT INTO protectors( mac, ip ) VALUES( $1, $2)', [mac, ip] )
                    this.ctx.body = {
                        subscribeKey : app.deviceSubKey,
                        subscribeChannel: app.deviceChannel + "/" + mac,
                        publishKey: app.monitorPubKey,
                        publishChannel: app.monitorChannel + "/" +  mac,
                        host: app.config.mqtt.host,
                        port: app.config.mqtt.port
                    }
                    this.ctx.status = 200
                }

            }
            catch( e ) {
                console.log( e );
                this.ctx.status = 400
                this.ctx.body = { error: e }
            }
        }


        /*
         * POST , /api/v1/security/shop
         * content-type: application/json
         * body:
         * {
         *  mac : # the protector mac
         *  shopid: #shop id
         *  cameras: # { "ip#channel": area_idx , ... }
         *  nvrs:  # { ip: { port: , password: , username: } , ....  }
         *  arm_areas: {
         *    1 :
         *    { x: ..., y: ..., l: ... ,}
         *       ....
         *    }
         *  },
         *  layers: [{
         *      name: "第一层",
         *      img_suffix: "png"/ "jpg"
         *  },
         *   .....
         *  ]
         * }
         * *****************
         * response :
         * content-type: application/json
         * body:
         * {
         * layers : [
         *      {
         *          Authorization: #authorization id for qcloud object storage
         *          layout_pic_url: #the url , webclient should use to upload layout pic
         *      },
         *      ...
         *  ]
         * }
         *
         * **************
         * config armAreas, and layers,  return the "authorizationId" and "layer_pic_url" on qcloude service  for each layer
         */

        async setShop( ) {
            try{
                console.log( 'update protector ', this.ctx.request.body )
                var request = this.ctx.request;
                var data = request.body


                var mac = data.mac

                var shopid = data.shopid;
                var arm_areas = data.arm_areas;

                var cameras = data.cameras;
                var nvrs = data.nvrs;

                var data_layers = data.layers
                var ret_layers = []
                var layers = []

                for( let i = 0; i < data_layers.length; i++ ){
                    var layout_pic_uri = QcloudBucket.Path + shopid + "_layer" + i +  data_layers[i].img_suffix
                    var authId = app.getAuthMyqcloud( 'put', layout_pic_uri )
                    var layout_pic_url = "http://" + QcloudBucket.Bucket  +".cos." + QcloudBucket.Region + ".myqcloud.com/"  + layout_pic_uri
                    ret_layers.push( { Authorization: authId,  layout_pic_url: layout_pic_url } )
                    layers.push( { layout_pic_url: layout_pic_url, name: data_layers[i].name } )
                }


                try{
                    await this.app.db.query( 'UPDATE protectors SET shopid = $1 WHERE mac = $2 ', [shopid, mac ] );
                    await this.app.db.query( 'UPDATE shops SET arm_areas = $1, layers = $2:json, cameras = $3, nvrs = $4 WHERE id = $5',
                        [  arm_areas, layers, cameras, nvrs,  shopid ] )
                } catch( error ) {
                    this.ctx.response.status = 400
                    this.ctx.response.body = { error: "UPDATE shops failed", info: error   }
                    return
                }

                this.ctx.status = 200
                this.ctx.body= { layers: ret_layers  }
                return
            } catch ( error ) {
                this.ctx.logger.error( 'get protectors error: ', error );
                console.log( error )
                this.ctx.status = 400
                this.ctx.body = { error: error }
                return
            }
        }



        /*
         * POST /api/v1/security/shop/arm
         */

        async oneClickSetAllArmAreas( ) {
            var data = this.ctx.request.body;
            data.mac = data.mac.replace( /\:/g , "" );
            try{
              var ret = await this.app.db.one( "SELECT arm_areas FROM protectors WHERE mac = $1 ", [data.mac] );
              var arm_areas = ret.arm_areas;
              var time_stamp = Date.now();
              for( let idx in arm_areas ) {
                  if( data.op == "chefang" ) {
                      arm_areas[idx].s = "c";
                      arm_areas[idx].t = time_stamp;
                  }
                  else if( data.op == "bufang" ) {
                      arm_areas[idx].s = "b";
                      arm_areas[idx].t = time_stamp ;
                  }
                  else{
                      console.log( 'unexpected' );
                  }
              }

              //TODO, send arm_areas config firstly
              if( data.op == "bufang" ) {
                  console.log( "---------------- publish bufang to, device/" + data.mac  );
                  app.mqtt.publish( "device/" + data.mac , "b" );
                  setTimeout(
                      ()=>{
                          app.mqtt.publish( "device/" + data.mac , "d" );
                          setTimeout(
                              () => {
                                  app.mqtt.publish( "device/" + data.mac , "a" ) ;
                              } ,  NORMAL_DELAY );
                  },  NORMAL_DELAY);
              }
              else if( data.op == "chefang" ) {
                  app.mqtt.publish( "device/" + data.mac, "b" )
                  setTimeout( ()=>{ app.mqtt.publish( "device/" + data.mac, "d" ); } , LONG_DELAY ) ;
              }
              else{
                  console.log( "unexpected op" );
                  return ;
              }
              await app.db.query( "UPDATE protectors  SET arm_areas = $1 WHERE mac = $2 ", [ arm_areas, data.mac ] )
            }
            catch( error) {
              console.log( "unexpected error: " , error ) ;
            }
            this.ctx.status = 200
            this.ctx.body = arm_areas;
        }


        //GET /api/v1/operateLogs
       async getOperateLogs() {
            try{
                var start = 0;
                var end = Date.now();
                var data = this.ctx.request.query;
                if( data && data.start ) {
                    start = data.start;

                }

                if( data && data.end ) {
                    end = data.end;
                }


                var logs = await app.db.query( 'SELECT * FROM protector_op_log WHERE stamp > $1 AND stamp < $2 ORDER BY stamp ASC', [ start, end ] );
                this.ctx.status = 200
                this.ctx.body = logs
            }
            catch( error ) {
                this.ctx.status = 500
                this.ctx.body =  error
            }
       }
       /*
        * PUT /api/v1/operateLog
        * content-type: application/json
        * body: {
        *   arm_area_idx:
        *   mac:
        * }
        * ----------------------------
        *  response:
        *  status: 200
        */

       async addOperateLog() {
           try{
               var data = this.ctx.request.body;
               var user = this.ctx.session.user;
               await app.db.query( 'INSERT INTO protector_op_log( stamp,  operation, mac, user_id ) VALUES( $1, $2, $3, $4 )', [ Date.now(), data.operation, data.mac,  user.mobile_phone ] );
               this.ctx.status = 200;
           }
           catch( error ) {
               console.log( "   get error: " , error );
               this.ctx.status = 500;
               this.ctx.body = error
           }
       }

       /*
        * GET /api/v1/security/alarmLogs
        * {
        *   start: timestamp/undefined  // default is 0
        *   limited:  integer // default is 50
        *   processed: false/true/undefined  // false , return no processed alarmlog, true: return processed alarmlog, undefined: return all alarmlogs
        * }
        *
        * ---------------------
        *  response:
        *
        * [ { stamp, user_id, process_result, process_time, arm_area_idx, mac } ]
        *
        */
       async getAlarmLogs() {
           try{
               var data = this.ctx.request.query;
               var start = 0;
               var limit = 200;
               var end = Date.now();
               if( data && data.start ) {
                   start = data.start;
               }

               if( data && data.limit ) {
                   limit = data.limit;
               }

               if( data && data.end ) {
                   end = data.end;
               }

               console.log( 'start: ', start );
               console.log( 'limit: ', limit );

               var result = null;
               var processed = false;
               if( data.processed === undefined ) {
                   result = await this.app.db.query( "SELECT shopid, stamp, user_id, process_result, process_time, arm_area_idx, mac FROM protector_alarm_log WHERE  stamp > $1 AND stamp < $3 ORDER BY stamp ASC LIMIT $2 ", [ start, limit, end  ] );
               }
               else if( data.processed === false ) {
                   result = await this.app.db.query( "SELECT shoid, stamp, user_id, process_result, process_time, arm_area_idx, mac FROM protector_alarm_log WHERE  stamp > $1  AND  stamp < $3 AND process_result ISNULL ORDER BY stamp ASC  LIMIT $2 " , [ start , limit, end ]);
               }
               else if( data.processed === true ) {
                   result = await this.app.db.query( "SELECT shopid, stamp, user_id, process_result, process_time, arm_area_idx, mac FROM protector_alarm_log WHERE  stamp > $1  AND  stamp < $3 AND process_result IS NOT NULL ORDER BY stamp ASC LIMIT $2 " , [ start, limit, end] );
               }

               this.ctx.status = 200;
               this.ctx.body = result;
           }
           catch( error ) {
               this.ctx.status = 500;
               console.log( "get alarmlogs failed: ", error );
               this.ctx.body = { error };
           }
       }

       /*
        * POST /api/v1/security/alarmLog
        * content-type: application/json
        * body : {
        *       mac: #the mac of protector which have been handled
        *       process_result: # user defined  handler
        * }
        *
        * ******************************
        * response:
        * status: 200
        *
        */
       async processAlarmLog() {
           try{
               var user_id = this.ctx.session.mobile_phone;
               var data = this.ctx.request.body;
               var result = await this.app.db.query( 'UPDATE protector_alarm_log SET user_id = $4, process_time = $3, process_result = $2 WHERE stamp=$1', [ data.stamp, data.process_result , Date.now(), user_id ] );
               this.ctx.status = 200;
               this.ctx.body = "success";
               console.log( "------------ success process alarm log " );
           }
           catch( error ) {
               console.log( "process alarm log " , + data.stamp + " error" );
               this.ctx.status = 500;
               this.ctx.body = { error }
           }
       }

       /*
        * PUT /api/v1/seucurity/alarmLog
        * content-type: application/json
        * body : {
        *       stamp:
        *       arm_area_idx:
        *       mac:
        * }
        */

       async addAlarmLog() {
           try{
               var data = this.ctx.request.body;
               var result = await this.app.db.query( 'INSERT INTO protector_alarm_log( stamp, arm_area_idx, mac ) VALUE( $1, $2, $3 )', [ Date.now(), data.arm_area_idx, data.mac ]  );
               this.ctx.status = 200;
               this.ctx.body = "success"
           }
           catch( error ) {
               this.ctx.status = 500;
               this.ctx.body = { error }
           }
       }

    }
    return SecurityController;
}

